package com.liuxinlong.modules.common.service.impl;

import com.alibaba.fastjson.JSON;
import com.liuxinlong.api.WeChatMessageInterface;
import com.liuxinlong.common.AosException;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.DifficultyStatusEnum;
import com.liuxinlong.enums.MessageContentTypeEnum;
import com.liuxinlong.enums.MessagePushBusinessEnum;
import com.liuxinlong.enums.PatentClassTypeEnum;
import com.liuxinlong.enums.PatentRiskTypeEnum;
import com.liuxinlong.enums.ProjectDealEnum;
import com.liuxinlong.enums.ProjectLevelEnum;
import com.liuxinlong.enums.ProjectPatentStageEnum;
import com.liuxinlong.enums.ProjectSourceEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.enums.WorkflowNodeTypeEnum;
import com.liuxinlong.enums.WorkflowTypeEnum;
import com.liuxinlong.modules.common.service.WorkFlowService;
import com.liuxinlong.modules.dao.PatentDepartmentDao;
import com.liuxinlong.modules.dao.PatentDepartmentSpecialDao;
import com.liuxinlong.modules.dao.PatentProposalDao;
import com.liuxinlong.modules.dao.PatentProposalHistoryDao;
import com.liuxinlong.modules.dao.PatentRiskDao;
import com.liuxinlong.modules.dao.PatentRiskHistoryDao;
import com.liuxinlong.modules.dao.PatentRiskProcessDao;
import com.liuxinlong.modules.dao.ProjectDao;
import com.liuxinlong.modules.dao.ProjectPatentExpandDao;
import com.liuxinlong.modules.dao.RoleDao;
import com.liuxinlong.modules.dao.UserDao;
import com.liuxinlong.modules.dao.UserMatterDao;
import com.liuxinlong.modules.dao.WorkFlowConfigDao;
import com.liuxinlong.modules.dao.WorkFlowDao;
import com.liuxinlong.modules.dao.WorkFlowGroupDao;
import com.liuxinlong.modules.dao.WorkFlowNodeConfigDao;
import com.liuxinlong.modules.dao.WorkFlowNodeRecordDao;
import com.liuxinlong.modules.entity.MessageConfiguration;
import com.liuxinlong.modules.entity.PatentDepartment;
import com.liuxinlong.modules.entity.PatentDepartmentSpecial;
import com.liuxinlong.modules.entity.PatentProposal;
import com.liuxinlong.modules.entity.PatentProposalHistory;
import com.liuxinlong.modules.entity.PatentRisk;
import com.liuxinlong.modules.entity.PatentRiskHistory;
import com.liuxinlong.modules.entity.PatentRiskProcess;
import com.liuxinlong.modules.entity.Project;
import com.liuxinlong.modules.entity.ProjectPatentExpand;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.entity.UserMatter;
import com.liuxinlong.modules.entity.WorkFlow;
import com.liuxinlong.modules.entity.WorkFlowConfig;
import com.liuxinlong.modules.entity.WorkFlowNodeConfig;
import com.liuxinlong.modules.entity.WorkFlowNodeRecord;
import com.liuxinlong.modules.patent.service.PatentProposalHistoryService;
import com.liuxinlong.modules.patent.service.PatentProposalService;
import com.liuxinlong.modules.patent.service.PatentRiskProcessService;
import com.liuxinlong.modules.system.service.FileManageService;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 工作流接口实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2024-04-23
 */
@Service
@Slf4j
public class WorkFlowServiceImpl implements WorkFlowService {
    @Autowired
    private UserDao userDao;

    @Autowired
    private WorkFlowConfigDao workFlowConfigDao;

    @Autowired
    private WorkFlowDao workFlowDao;

    @Autowired
    private WorkFlowNodeConfigDao workFlowNodeConfigDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private WorkFlowNodeRecordDao workFlowNodeRecordDao;

//    @Autowired
//    private UserMatterService userMatterService;

    @Autowired
    private WeChatMessageInterface weChatMessageInterface;

    @Autowired
    private UserMatterDao userMatterDao;

    @Autowired
    private WorkFlowGroupDao workFlowGroupDao;

    @Autowired
    private ProjectDao projectDao;

    @Autowired
    private PatentDepartmentDao patentDepartmentDao;

    @Autowired
    private PatentDepartmentSpecialDao patentDepartmentSpecialDao;

    @Autowired
    private FileManageService fileManageService;

    @Autowired
    private PatentProposalService patentProposalService;

    @Autowired
    private PatentRiskDao patentRiskDao;

    @Autowired
    private PatentProposalDao patentProposalDao;

    @Autowired
    private ProjectPatentExpandDao projectPatentExpandDao;

    @Autowired
    private PatentRiskProcessDao patentRiskProcessDao;

    @Autowired
    private PatentRiskProcessService patentRiskProcessService;

    @Autowired
    private PatentRiskHistoryDao patentRiskHistoryDao;

    @Autowired
    private PatentProposalHistoryDao patentProposalHistoryDao;

    @Autowired
    private PatentProposalHistoryService patentProposalHistoryService;

    @Override
    public List<Map<String, Object>> queryWorkflowConfigList(Map<String, Object> queryParam) {
        List<WorkFlowConfig> originalList = workFlowConfigDao.pageWorkflowConfigList(queryParam);
        List<Map<String, Object>> dataList = new ArrayList<>(originalList.size());
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        int sort = (int) queryParam.get("startNum") + 1;
        for (WorkFlowConfig config : originalList) {
            Map<String, Object> item = ObjectUtils.object2Map(config);
            item.put("sort", sort);
            item.put("userName", userMap.containsKey(config.getCreateUser()) ? userMap.get(config.getCreateUser()).get("name") : null);
            item.put("statusName", config.getStatus() == 1 ? "生效" : "未生效");
            item.put("businessTypeName", WorkflowTypeEnum.getNameByValue(config.getBusinessType()));
            dataList.add(item);
            sort++;
        }
        return dataList;
    }

    @Override
    public int getWorkflowConfigCount(Map<String, Object> queryParam) {
        return workFlowConfigDao.getWorkflowConfigCount(queryParam);
    }

    @Override
    @Transactional
    public void addWorkflowConfig(WorkFlowConfig workFlowConfig) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        String id = SnowFlake.nextIdStr();
        workFlowConfig.setId(id);
        workFlowConfig.setStatus(2);
        workFlowConfig.setCreateUser(currentUser.getId());
        workFlowConfig.setCreateTime(currentTime);
        workFlowConfigDao.insert(workFlowConfig);
        WorkFlowNodeConfig nodeConfig = new WorkFlowNodeConfig();
        nodeConfig.setId(SnowFlake.nextIdStr());
        nodeConfig.setConfigId(id);
        nodeConfig.setNodeName("开始");
        nodeConfig.setContent("开始");
        nodeConfig.setNodeType(WorkflowNodeTypeEnum.NODE_TYPE_START.getValue());
        nodeConfig.setNoticeType(0);
        nodeConfig.setSortNum(1);
        nodeConfig.setReviewType(0);
        workFlowNodeConfigDao.insert(nodeConfig);
        WorkFlowNodeConfig endNodeConfig = new WorkFlowNodeConfig();
        endNodeConfig.setId(SnowFlake.nextIdStr());
        endNodeConfig.setConfigId(id);
        endNodeConfig.setNodeName("结束");
        endNodeConfig.setContent("结束");
        endNodeConfig.setNodeType(WorkflowNodeTypeEnum.NODE_TYPE_END.getValue());
        endNodeConfig.setNoticeType(0);
        endNodeConfig.setSortNum(2);
        endNodeConfig.setReviewType(0);
        workFlowNodeConfigDao.insert(endNodeConfig);
    }

    @Override
    @Transactional
    public void updateWorkflowConfig(WorkFlowConfig workFlowConfig) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        Map<String, Object> query = new HashMap<>();
        query.put("configId", workFlowConfig.getId());
        int existFlow = workFlowDao.getWorkflowCount(query);
        if (existFlow > 0) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，存在流程记录！");
        }
        WorkFlowConfig oldInfo = workFlowConfigDao.selectById(workFlowConfig.getId());
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，原配置信息不存在！");
        }
        workFlowConfig.setStatus(oldInfo.getStatus());
        workFlowConfig.setUpdateUser(currentUser.getId());
        workFlowConfig.setUpdateTime(currentTime);
        workFlowConfigDao.updateById(workFlowConfig);
    }

    @Override
    public void deleteWorkflowConfig(String id) {
        Map<String, Object> query = new HashMap<>();
        query.put("configId", id);
        int existFlow = workFlowDao.getWorkflowCount(query);
        if (existFlow > 0) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除失败，存在流程记录！");
        }
        workFlowConfigDao.deleteById(id);
    }

    @Override
    public List<Map<String, Object>> pageWorkflowNodeConfig(String configId) {
        List<WorkFlowNodeConfig> nodeList = workFlowNodeConfigDao.getWorkflowNodeConfigList(configId);
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        Map<String, Map<String, String>> roleMap = roleDao.getRoleMap();
        Map<String, Map<String, String>> groupMap = workFlowGroupDao.getGroupMap();
        List<Map<String, Object>> dataList = new ArrayList<>(nodeList.size());
        int sort = 1;
        for (WorkFlowNodeConfig node : nodeList) {
            Map<String, Object> item = ObjectUtils.object2Map(node);
            item.put("sort", sort);
            item.put("key", node.getId());
            item.put("nodeTypeName", WorkflowNodeTypeEnum.getNameByValue(node.getNodeType()));
            item.put("noticeTypeName", node.getNoticeType() == 1 ? "是" : "否");
            item.put("reviewTypeName", node.getReviewType() == 1 ? "个签" : "会签");
            List<String> groupName = new ArrayList<>();
            if (!StringUtils.isEmpty(node.getOperateGroup())) {
                List<String> groupList = Arrays.asList(node.getOperateGroup().split(","));
                for (String group : groupList) {
                    groupName.add(groupMap.containsKey(group) ? groupMap.get(group).get("name") : "");
                }
            }
            item.put("operateGroupName", StringUtils.strip(groupName.toString(), "[]"));
            item.put("operateRoleName", roleMap.containsKey(node.getOperateRole()) ? roleMap.get(node.getOperateRole()).get("name") : "");
            List<String> userName = new ArrayList<>();
            if (!StringUtils.isEmpty(node.getOperateUser())) {
                List<String> userList = Arrays.asList(node.getOperateUser().split(","));
                for (String user : userList) {
                    userName.add(userMap.containsKey(user) ? userMap.get(user).get("name") : "");
                }
            }
            item.put("operateUserName", StringUtils.strip(userName.toString(), "[]"));
            dataList.add(item);
            sort++;
        }
        return dataList;
    }

    @Override
    public void updateWorkflowNodeConfig(String configId, List<WorkFlowNodeConfig> nodeList) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        Map<String, Object> query = new HashMap<>();
        query.put("configId", configId);
//        query.put("status", 1);
        int existFlow = workFlowDao.getWorkflowCount(query);
        if (existFlow > 0) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，存在流程记录！");
        }
        workFlowNodeConfigDao.deleteByConfigId(configId);
        boolean haveStart = false;
        boolean haveEnd = false;
        int minNode = nodeList.size();
        int maxNode = 0;
        int endNode = 0;
        int startNode = 0;
        List<WorkFlowNodeConfig> newNodeList = new ArrayList<>(nodeList.size());
        for (WorkFlowNodeConfig node : nodeList) {
            if (haveStart && node.getNodeType() == WorkflowNodeTypeEnum.NODE_TYPE_START.getValue()) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "包含多个开始节点！");
            }
            if (haveEnd && node.getNodeType() == WorkflowNodeTypeEnum.NODE_TYPE_END.getValue()) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "包含多个结束节点！");
            }
            if (node.getNodeType() == WorkflowNodeTypeEnum.NODE_TYPE_START.getValue()) {
                haveStart = true;
                startNode = node.getSortNum();
            }
            if (node.getNodeType() == WorkflowNodeTypeEnum.NODE_TYPE_END.getValue()) {
                haveEnd = true;
                endNode = node.getSortNum();
            }
            if (StringUtils.isEmpty(node.getId())) {
                node.setId(SnowFlake.nextIdStr());
                node.setConfigId(configId);
            }
            maxNode = Math.max(node.getSortNum(), maxNode);
            minNode = Math.min(node.getSortNum(), minNode);
            newNodeList.add(node);
        }
        if (!haveStart || !haveEnd) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "缺少起止节点！");
        }
        if (maxNode > endNode) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "结束节点应在流程最后！");
        }
        if (minNode < startNode) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "开始节点应在流程最前！");
        }
        if (!ObjectUtils.isEmpty(newNodeList)) {
            workFlowNodeConfigDao.insertBatch(newNodeList);
        }
        WorkFlowConfig config = workFlowConfigDao.selectById(configId);
        config.setUpdateUser(currentUser.getId());
        config.setUpdateTime(currentTime);
        workFlowConfigDao.updateById(config);
    }

    @Override
    public List<Map<String, Object>> queryWorkflowList(Map<String, Object> queryParam) {
        List<WorkFlow> originalList = workFlowDao.pageWorkflowList(queryParam);
        List<Map<String, Object>> dataList = new ArrayList<>(originalList.size());
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        Map<String, Map<String, Object>> configMap = workFlowConfigDao.getWorkflowConfigMap();
        int sort = (int) queryParam.get("startNum") + 1;
        for (WorkFlow flow : originalList) {
            Map<String, Object> item = ObjectUtils.object2Map(flow);
            item.put("sort", sort);
            item.put("userName", userMap.containsKey(flow.getCreateUser()) ? userMap.get(flow.getCreateUser()).get("name") : null);
            if (configMap.containsKey(flow.getConfigId())) {
                Map<String, Object> config = configMap.get(flow.getConfigId());
                item.put("flowName", config.get("name"));
                item.put("businessTypeName", WorkflowTypeEnum.getNameByValue((Integer) config.get("businessType")));
                item.put("configStatusName", (int) config.get("status") == 1 ? "启用" : "未启用");
            }
            item.put("statusName", flow.getStatus() == 1 ? "进行中" : flow.getStatus() == 2 ? "已完成" : "废止");
            dataList.add(item);
            sort++;
        }
        return dataList;
    }

    @Override
    public int getWorkflowCount(Map<String, Object> queryParam) {
        return workFlowDao.getWorkflowCount(queryParam);
    }

    @Override
    public void updateWorkflowConfigStatus(String configId) {
        WorkFlowConfig config = workFlowConfigDao.selectById(configId);
        if (ObjectUtils.isEmpty(config)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，原配置信息不存在！");
        }
        if (config.getStatus() == 1) {
            Map<String, Object> query = new HashMap<>();
            query.put("configId", configId);
            query.put("status", 1);
            int existFlow = workFlowDao.getWorkflowCount(query);
            if (existFlow > 0) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，存在进行中流程记录！");
            }
            config.setStatus(2);
        } else {
            Map<String, Object> query = new HashMap<>();
            query.put("businessType", config.getBusinessType());
            query.put("status", 1);
            int effectiveNum = workFlowConfigDao.getWorkflowConfigCount(query);
            if (effectiveNum > 0) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，存在生效中流程配置！");
            }
            config.setStatus(1);
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        config.setUpdateTime(currentTime);
        config.setUpdateUser(currentUser.getId());
        workFlowConfigDao.updateById(config);
    }

    @Override
    @Transactional
    public void startWorkflow(String businessId, int configType, String expand) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        WorkFlowConfig workFlowConfig = workFlowConfigDao.getEffectiveBusinessWorkflow(configType);
        if (ObjectUtils.isEmpty(workFlowConfig)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "流程未配置！");
        }
        String configId = workFlowConfig.getId();
        Map<String, Object> query = new HashMap<>();
        query.put("businessId", businessId);
        query.put("status", 1);
        query.put("configId", configId);
        int dbCount = workFlowDao.getWorkflowCount(query);
        if (dbCount > 0) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "存在进行中流程，请等待流程结束后再次发起！");
        }
        Project project = new Project();
        if (configType == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() || configType == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue()) {
            project = projectDao.selectById(businessId);
            ProjectPatentExpand patentExpand = projectPatentExpandDao.selectById(businessId);
            if (configType == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() && (patentExpand.getChildStage() != 1 && patentExpand.getChildStage() != 5)) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "流程发起失败，请等待新品项目专利分析流程结束！");
            } else if (configType == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue() && patentExpand.getChildStage() != 3) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "流程发起失败，请等待项目专利排查流程结束！");
            }
            patentExpand.setUpdateTime(currentTime);
            patentExpand.setUpdateUser(currentUser.getId());
            patentExpand.setChildStage(configType == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() ? 2 : 5);
            projectPatentExpandDao.updateById(patentExpand);
        }
        String workflowId = SnowFlake.nextIdStr();
        String childId = "";
        if (configType == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue()) {
            PatentRiskProcess currentSortProcess = patentRiskProcessDao.getCurrentSort(businessId);
            PatentRiskProcess patentRiskProcess = new PatentRiskProcess();
            String processId = SnowFlake.nextIdStr();
            patentRiskProcess.setId(processId);
            patentRiskProcess.setProjectId(businessId);
            patentRiskProcess.setSortNum(ObjectUtils.isEmpty(currentSortProcess) ? 1 : currentSortProcess.getSortNum() + 1);
            Map<String, Object> applyData = JSON.parseObject(expand);
            patentRiskProcess.setRiskStage((Integer) applyData.get("stage"));
            patentRiskProcess.setStartTime(currentTime);
            patentRiskProcess.setStatus(1);
            patentRiskProcessDao.insert(patentRiskProcess);
            backupData(businessId,workflowId);
            childId = processId;
        } else if (configType == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue()) {
//            PatentRiskProcess currentSortProcess = patentRiskProcessDao.getCurrentSort(businessId);
            WorkFlow investigationFlow = workFlowDao.getBusinessLatestWorkflow(businessId);
            expand = investigationFlow.getContent();
            childId = investigationFlow.getChildId();
            backupData(businessId,workflowId);
        }

        List<WorkFlowNodeConfig> nodeConfigList = workFlowNodeConfigDao.getWorkflowNodeConfigList(configId);
        Map<String, Map<String, String>> groupMap = workFlowGroupDao.getGroupMap();
        List<WorkFlowNodeRecord> recordAddList = new ArrayList<>();
        List<UserMatter> addMatterList = new ArrayList<>();
        for (WorkFlowNodeConfig nodeConfig : nodeConfigList) {
            if (nodeConfig.getSortNum() > 2) {
                continue;
            }
            if (nodeConfig.getSortNum() == 1) {
                WorkFlowNodeRecord workFlowNodeRecord = creatWorkFlowNodeRecord(nodeConfig, workflowId, currentTime, currentUser.getId(), currentUser.getId());
                workFlowNodeRecord.setResult(1);
                recordAddList.add(workFlowNodeRecord);
            }
            if (nodeConfig.getSortNum() == 2) {
                String content = "用户 " + currentUser.getName() + " 发起" +
                        (configType == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() ? "项目风险排查" :
                                configType == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue() ? "新品专利风险分析" :
                                        configType == WorkflowTypeEnum.PATENT_RISK.getValue() ? "风险专利评估" : "")
                        + "需求，请登录审批";
                List<String> messageList = new ArrayList<>();
                if (StringUtils.isEmpty(nodeConfig.getOperateUser())) {
                    // 增加待处理用户组
                    List<String> groupList = Arrays.asList(nodeConfig.getOperateGroup().split(","));
                    for (String group : groupList) {
                        String matchUser = matchSystemGroup(group, project);
                        if (!StringUtils.equals(matchUser, "noMatch")) {
                            if (matchUser.contains(",")) {
                                List<String> userList = Arrays.asList(matchUser.split(","));
                                messageList.addAll(userList);
                                for (String u : userList) {
                                    WorkFlowNodeRecord workFlowNodeRecord = creatWorkFlowNodeRecord(nodeConfig, workflowId, currentTime, currentUser.getId(), u);
                                    recordAddList.add(workFlowNodeRecord);
                                    UserMatter userMatter = createMatter(currentTime, content, workflowId, u);
                                    userMatter.setSourceType(workFlowConfig.getBusinessType() + 6);
                                    addMatterList.add(userMatter);
                                }
                                continue;
                            }
                            messageList.add(matchUser);
                            WorkFlowNodeRecord workFlowNodeRecord = creatWorkFlowNodeRecord(nodeConfig, workflowId, currentTime, currentUser.getId(), matchUser);
                            recordAddList.add(workFlowNodeRecord);
                            UserMatter userMatter = createMatter(currentTime, content, workflowId, matchUser);
                            userMatter.setSourceType(workFlowConfig.getBusinessType() + 6);
                            addMatterList.add(userMatter);
                            continue;
                        }
                        List<String> groupUserList = Arrays.asList(groupMap.get(group).get("groupUser").split(","));
                        for (String groupUser : groupUserList) {
                            UserMatter userMatter = createMatter(currentTime, content, workflowId, groupUser);
                            userMatter.setSourceType(workFlowConfig.getBusinessType() + 6);
                            addMatterList.add(userMatter);
                            WorkFlowNodeRecord workFlowNodeRecord = creatWorkFlowNodeRecord(nodeConfig, workflowId, currentTime, currentUser.getId(), groupUser);
                            recordAddList.add(workFlowNodeRecord);
                        }
                        messageList.addAll(groupUserList);
                    }
                } else {
                    List<String> targetUserList = Arrays.asList(nodeConfig.getOperateUser().split(","));
                    for (String targetUser : targetUserList) {
                        UserMatter userMatter = createMatter(currentTime, content, workflowId, targetUser);
                        userMatter.setSourceType(workFlowConfig.getBusinessType() + 6);
                        addMatterList.add(userMatter);
                        WorkFlowNodeRecord workFlowNodeRecord = creatWorkFlowNodeRecord(nodeConfig, workflowId, currentTime, currentUser.getId(), targetUser);
                        recordAddList.add(workFlowNodeRecord);
                    }
                    messageList.addAll(targetUserList);
                }
                if (!addMatterList.isEmpty()) {
                    userMatterDao.insertBatch(addMatterList);
                }
                if (nodeConfig.getNoticeType() == 1) {
                    MessageConfiguration messageConfiguration = new MessageConfiguration();
                    messageConfiguration.setBusinessType(MessagePushBusinessEnum.PATENT_RISK_PROCESS.getValue());
                    messageConfiguration.setContent(content);
                    messageConfiguration.setContentType(MessageContentTypeEnum.TEXT_CARD.getValue());
                    weChatMessageInterface.pushMessage(messageList, null, messageConfiguration, currentTime);
                }
            }
//            recordAddList.add(workFlowNodeRecord);
        }
        if (!recordAddList.isEmpty()) {
            workFlowNodeRecordDao.insertBatch(recordAddList);
        }
        WorkFlow workFlow = new WorkFlow();
        workFlow.setId(workflowId);
        workFlow.setBusinessId(businessId);
        workFlow.setChildId(childId);
        workFlow.setConfigId(workFlowConfig.getId());
        workFlow.setCurrentNode(2);
        workFlow.setStatus(1);
        workFlow.setContent(expand);
        workFlow.setCreateUser(currentUser.getId());
        workFlow.setCreateTime(currentTime);
        workFlowDao.insert(workFlow);
    }

    @Override
    public void dealWorkflow(String id, int result, String dealOpinions) {
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        WorkFlow workFlow = workFlowDao.selectById(id);
        if (workFlow.getStatus() > 1) {
            return;
        }
        WorkFlowNodeConfig config = workFlowNodeConfigDao.getByWorkflowNode(workFlow.getConfigId(), workFlow.getCurrentNode());
        List<WorkFlowNodeRecord> recordList = workFlowNodeRecordDao.getCurrentEffectiveRecord(id, workFlow.getCurrentNode());
        Map<String, UserMatter> userMatterMap = userMatterDao.getSourceUserMatterMap(id);
        List<UserMatter> updateMatterList = new ArrayList<>();
        List<WorkFlowNodeRecord> updateList = new ArrayList<>();
        String userId = currentUser.getId();
        if (config.getReviewType() == 1) {
            for (WorkFlowNodeRecord record : recordList) {
                record.setUpdateTime(currentTime);
                record.setUpdateUser(userId);
                record.setStatus(2);
                UserMatter userMatter = userMatterMap.get(record.getDealUser());
                if (StringUtils.equals(record.getDealUser(), userId)) {
                    record.setResult(result);
                    record.setDealOpinions(dealOpinions);
                    updateList.add(record);
                    userMatter.setDealUser(userId);
                    userMatter.setStatus(1);
                    updateMatterList.add(userMatter);
                    continue;
                }
                record.setResult(4);
                updateList.add(record);
                userMatter.setDealTime(currentTime);
                userMatter.setStatus(3);
                updateMatterList.add(userMatter);
            }
        } else {
            if (result == 2) {
                for (WorkFlowNodeRecord record : recordList) {
                    record.setUpdateTime(currentTime);
                    record.setUpdateUser(userId);
                    record.setStatus(2);
                    UserMatter userMatter = userMatterMap.get(record.getDealUser());
                    if (StringUtils.equals(record.getDealUser(), userId)) {
                        record.setResult(result);
                        record.setDealOpinions(dealOpinions);
                        updateList.add(record);
                        userMatter.setDealUser(userId);
                        userMatter.setStatus(1);
                        updateMatterList.add(userMatter);
                        continue;
                    }
                    record.setResult(4);
                    updateList.add(record);
                    userMatter.setStatus(3);
                    updateMatterList.add(userMatter);
                }
            } else {
                for (WorkFlowNodeRecord record : recordList) {
                    if (!StringUtils.equals(record.getDealUser(), userId)) {
                        continue;
                    }
                    record.setUpdateTime(currentTime);
                    record.setUpdateUser(userId);
                    record.setStatus(2);
                    record.setResult(result);
                    record.setDealOpinions(dealOpinions);
                    updateList.add(record);
                    UserMatter userMatter = userMatterMap.get(userId);
                    userMatter.setDealUser(userId);
                    userMatter.setStatus(1);
                    updateMatterList.add(userMatter);
                }
            }
        }
        if (updateList.size() > 0) {
            workFlowNodeRecordDao.updateBatchById(updateList);
        }
        if (updateMatterList.size() > 0) {
            userMatterDao.updateBatchById(updateMatterList);
        }
        if (result == 2) {
            sendBack(workFlow, currentTime, currentUser);
        } else {
            if (config.getReviewType() == 1 || updateList.size() == recordList.size()) {
                nextFlow(workFlow, currentTime, currentUser);
            }
        }
    }

    @Override
    @Transactional
    public Map<String, Object> queryWorkflowDetail(String id, String childId) {
        Map<String, Object> dataMap = new HashMap<>();
        WorkFlow workFlow;
        if (!StringUtils.isEmpty(id)) {
            workFlow = workFlowDao.selectById(id);
        } else {
            if (StringUtils.isEmpty(childId)) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "工作流不存在！");
            }
            Map<String,Object> queryParam = new HashMap<>();
            queryParam.put("childId",childId);
            queryParam.put("businessType",WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue());
            queryParam.put("startNum",0);
            queryParam.put("pageSize",10000);
            List<WorkFlow> workFlowList = workFlowDao.pageWorkflowList(queryParam);
            if (workFlowList.isEmpty()) {
                dataMap.put("projectData", new HashMap<>());
                dataMap.put("planList",new ArrayList<>());
                dataMap.put("applyData", new HashMap<>());
                dataMap.put("proposalList", new ArrayList<>());
                return dataMap;
            }
            workFlow = workFlowList.get(0);
        }
        if (ObjectUtils.isEmpty(workFlow)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "工作流不存在！");
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        WorkFlowConfig config = workFlowConfigDao.selectById(workFlow.getConfigId());
        if (config.getBusinessType() == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() ||
                config.getBusinessType() == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue()) {
            String projectId = workFlow.getBusinessId();
            // 项目信息
            Project project = projectDao.selectById(projectId);
            Map<String, Object> projectData = buildProject(project, userMap);
            dataMap.put("projectData", projectData);
            // 设计差异点信息
            Map<String, Object> query = new HashMap<>();
            query.put("projectId", projectId);
            query.put("processId", workFlow.getId());
            query.put("startNum", 0);
            query.put("pageSize", 10000);
            List<PatentRiskHistory> patentRiskList = patentRiskHistoryDao.pagePatentRiskHistoryList(query);
            List<Map<String, Object>> planList = new ArrayList<>(patentRiskList.size());
            int sort = 1;
            for (PatentRiskHistory risk : patentRiskList) {
                Map<String, Object> item = ObjectUtils.object2Map(risk);
                item.put("sort", sort);
                Map<String, Object> fileMap = fileManageService.queryFileManageInfos(risk.getRiskId());
                if (fileMap.containsKey("39")) {
                    item.put("pictureUrl", fileMap.get("39"));
                }
                planList.add(item);
                sort++;
            }
            dataMap.put("planList", planList);
            // 申请信息
            Map<String, Object> applyData = JSON.parseObject(workFlow.getContent());
            applyData.put("createDate", workFlow.getCreateTime());
            applyData.put("applyUser", userMap.containsKey(workFlow.getCreateUser()) ? userMap.get(workFlow.getCreateUser()).get("name") : "");
            applyData.put("department", projectData.get("departmentName"));
            applyData.put("stageName", ProjectPatentStageEnum.getNameByValue((Integer) applyData.get("stage")));
            dataMap.put("applyData", applyData);
        } else if (config.getBusinessType() == WorkflowTypeEnum.PATENT_RISK.getValue()) {
            // 风险专利评估
            PatentProposal patentProposal = patentProposalDao.selectById(workFlow.getBusinessId());
            if (ObjectUtils.isEmpty(patentProposal)) {
                throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "专利信息不存在！");
            }
            if (StringUtils.isEmpty(patentProposal.getProjectId())) {
                dataMap.put("projectData", new HashMap<>());
            } else {
                // 项目信息
                Project project = projectDao.selectById(patentProposal.getProjectId());
                Map<String, Object> projectData = buildProject(project, userMap);
                dataMap.put("projectData", projectData);
            }
            List<Map<String, Object>> dataList = new ArrayList<>();
            Map<String, Object> map = ObjectUtils.object2Map(patentProposal);
            map.put("classTypeName", PatentClassTypeEnum.getNameByValue(patentProposal.getClassType()));
            map.put("statusName", patentProposal.getStatus());
            map.put("riskTypeName", patentProposal.getRiskType() == 1 ? "侵权" : "不侵权");
            map.put("levelName", patentProposal.getLevel() == 1 ? "高风险" : patentProposal.getLevel() == 2 ? "低风险" : patentProposal.getLevel() == 3 ? "无风险" : "未定义");
            dataList.add(map);
            dataMap.put("dataList", dataList);
            // 申请信息
            Map<String, Object> applyData = JSON.parseObject(workFlow.getContent());
            applyData.put("createDate", workFlow.getCreateTime());
            applyData.put("applyUser", userMap.containsKey(workFlow.getCreateUser()) ? userMap.get(workFlow.getCreateUser()).get("name") : "");
            dataMap.put("applyData", applyData);
        }
        if (config.getBusinessType() == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue()) {
            Map<String, Object> query = new HashMap<>();
            query.put("processId", workFlow.getId());
            query.put("projectId", workFlow.getBusinessId());
            query.put("startNum", 0);
            query.put("pageSize", 10000);
            List<Map<String, Object>> proposalList = patentProposalHistoryService.pagePatentProposalHistoryInfo(query);
            dataMap.put("proposalList", proposalList);
        }
        List<WorkFlowNodeRecord> recordList = workFlowNodeRecordDao.getFinishedWorkflowRecord(workFlow.getId());
        List<WorkFlowNodeConfig> nodeConfigList = workFlowNodeConfigDao.getWorkflowNodeConfigList(workFlow.getConfigId());
        Map<Integer, WorkFlowNodeConfig> nodeConfigMap = new HashMap<>();
        WorkFlowNodeConfig endNodeConfig = new WorkFlowNodeConfig();
        for (WorkFlowNodeConfig nodeConfig : nodeConfigList) {
            nodeConfigMap.put(nodeConfig.getSortNum(), nodeConfig);
            if (nodeConfig.getNodeType() == 2) {
                endNodeConfig = nodeConfig;
            }
        }
        List<Map<String, Object>> nodeRecordList = new ArrayList<>(recordList.size());
        Set<Integer> nodeConfigSet = new HashSet<>();
        int sort = 1;
        for (WorkFlowNodeRecord record : recordList) {
            Map<String, Object> item = ObjectUtils.object2Map(record);
            WorkFlowNodeConfig nodeConfig = nodeConfigMap.get(record.getNode());
            item.put("dealUserName", userMap.containsKey(record.getDealUser()) ? userMap.get(record.getDealUser()).get("name") : "");
            item.put("dealTypeName", nodeConfig.getNodeType() == 2 ? "流程结束" : nodeConfig.getNodeType() == 1 ? "流程发起" : "审核");
            item.put("resultName", record.getResult() == 1 ? "通过" : record.getResult() == 2 ? "拒绝" : record.getResult() == 3 ? "未处理" : record.getResult() == 4 ? "自动处理通过（他人已办）" : "未处理");
            item.put("sort", sort);
            item.put("nodeName", nodeConfig.getContent());
            nodeConfigSet.add(record.getNode());
            nodeRecordList.add(item);
            sort++;
        }
        // 申请人可查看全部流程节点
        if (StringUtils.equals(currentUser.getId(), workFlow.getCreateUser())) {
//            List<WorkFlowNodeConfig> nodeConfigList = workFlowNodeConfigDao.getWorkflowNodeConfigList(workFlow.getConfigId());
            // 未处理流程节点
            if (nodeConfigList.size() > nodeConfigSet.size()) {
                for (WorkFlowNodeConfig nodeConfig : nodeConfigList) {
                    if (nodeConfigSet.contains(nodeConfig.getSortNum())) {
                        continue;
                    }
                    Map<String, Object> item = new HashMap<>();
                    item.put("sort", sort);
                    item.put("node", nodeConfig.getSortNum());
                    item.put("nodeName", nodeConfig.getNodeName());
                    item.put("dealTypeName", !ObjectUtils.isEmpty(endNodeConfig) && nodeConfig.getSortNum() == endNodeConfig.getSortNum() ? "流程结束" : nodeConfig.getSortNum() == 1 ? "流程发起" : "审核");

                    item.put("status", 3);
                    item.put("config", nodeConfig);
                    nodeRecordList.add(item);
                    sort++;
                }
            }
        }

        dataMap.put("recordList", nodeRecordList);
        return dataMap;
    }

    @Override
    public void urgingWorkflow(String id, String targetUser) {
        //todo
    }

    @Override
    public void recallWorkflow(String id) {
        //todo
    }

    @Override
    public Map<String, Object> queryWorkflowRecordDetail(String id) {
        WorkFlow workFlow = workFlowDao.selectById(id);
        if (ObjectUtils.isEmpty(workFlow)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "流程记录不存在！");
        }
        Map<String, Object> dataMap = new HashMap<>();
        WorkFlowConfig workFlowConfig = workFlowConfigDao.selectById(workFlow.getConfigId());
        if (ObjectUtils.isEmpty(workFlowConfig)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "流程配置不存在！");
        }

        dataMap.put("businessType", workFlowConfig.getBusinessType());
        if (workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() || workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue()) {
            Map<String, Object> businessMap = JSON.parseObject(workFlow.getContent());
            Project project = projectDao.selectById(workFlow.getBusinessId());
            businessMap.put("projectName", project.getProjectName());
            businessMap.put("projectLevelName", ProjectLevelEnum.getNameByValue(project.getProjectLevel()));
            businessMap.put("projectTypeName", project.getProjectType() == 1 ? "预研项目" : project.getProjectType() == 2 ? "新品开发" : project.getProjectType() == 3 ? "其他" : "未知类型");
            businessMap.put("departmentName", patentDepartmentDao.selectById(project.getDepartment()).getName());
            dataMap.put("businessMap", businessMap);
        }
        List<WorkFlowNodeRecord> workFlowNodeRecordList = workFlowNodeRecordDao.getWorkflowRecord(id);
        List<WorkFlowNodeConfig> nodeConfigList = workFlowNodeConfigDao.getWorkflowNodeConfigList(workFlow.getConfigId());
        Map<Integer, WorkFlowNodeConfig> nodeConfigMap = new HashMap<>();
        for (WorkFlowNodeConfig nodeConfig : nodeConfigList) {
            nodeConfigMap.put(nodeConfig.getSortNum(), nodeConfig);
        }
        Set<Integer> nodeConfigSet = new HashSet<>();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        List<Map<String, Object>> dataList = new ArrayList<>(workFlowNodeRecordList.size());
        int sort = 1;
        for (WorkFlowNodeRecord record : workFlowNodeRecordList) {
            Map<String, Object> item = ObjectUtils.object2Map(record);
            item.put("sort", sort);
            if (nodeConfigMap.containsKey(record.getNode())) {
                item.put("config", nodeConfigMap.get(record.getNode()));
                nodeConfigSet.add(record.getNode());
            }
            item.put("dealUserName", userMap.containsKey(record.getDealUser()) ? userMap.get(record.getDealUser()).get("name") : "");
            item.put("resultName", record.getResult() == 1 ? "通过" : record.getResult() == 2 ? "拒绝" : record.getResult() == 3 ? "未处理" : record.getResult() == 4 ? "自动处理通过（他人已办）" : "未处理");
            dataList.add(item);
            sort++;
        }
        // 未处理流程节点
        if (nodeConfigList.size() > nodeConfigSet.size()) {
            for (WorkFlowNodeConfig nodeConfig : nodeConfigList) {
                if (nodeConfigSet.contains(nodeConfig.getSortNum())) {
                    continue;
                }
                Map<String, Object> item = new HashMap<>();
                item.put("sort", sort);
                item.put("node", nodeConfig.getSortNum());
                item.put("status", 3);
                item.put("config", nodeConfig);
                dataList.add(item);
                sort++;
            }
        }
        dataMap.put("recordList", dataList);
        return dataMap;
    }

    @Override
    public void updateWorkflowRecord(String flowId, int dealType, String dealOpinions) {
        WorkFlow workFlow = workFlowDao.selectById(flowId);
        if (ObjectUtils.isEmpty(workFlow)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "流程记录不存在！");
        }
        WorkFlowNodeConfig config = workFlowNodeConfigDao.getByWorkflowNode(workFlow.getConfigId(), workFlow.getCurrentNode());
        List<WorkFlowNodeRecord> recordList = workFlowNodeRecordDao.getCurrentEffectiveRecord(flowId, workFlow.getCurrentNode());
        Map<String, UserMatter> userMatterMap = userMatterDao.getSourceUserMatterMap(flowId);
        List<UserMatter> updateMatterList = new ArrayList<>();
        List<WorkFlowNodeRecord> updateList = new ArrayList<>();
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String userId = currentUser.getId();
        if (dealType == 1) {
            for (WorkFlowNodeRecord record : recordList) {
                record.setUpdateTime(currentTime);
                record.setUpdateUser(userId);
                record.setStatus(2);
                UserMatter userMatter = userMatterMap.get(record.getDealUser());
                record.setResult(4);
                updateList.add(record);
                userMatter.setDealTime(currentTime);
                userMatter.setStatus(3);
                updateMatterList.add(userMatter);
            }
            if (updateList.size() > 0) {
                workFlowNodeRecordDao.updateBatchById(updateList);
            }
            if (updateMatterList.size() > 0) {
                userMatterDao.updateBatchById(updateMatterList);
            }
            if (config.getReviewType() == 1 || updateList.size() == recordList.size()) {
                nextFlow(workFlow, currentTime, currentUser);
            }
        } else if (dealType == 2) {

        } else if (dealType == 3) {

        } else if (dealType == 4) {

        }
    }

    @Override
    public List<Map<String, Object>> queryBusinessWorkflowRecord(String businessId, int businessType) {
        return null;
    }

    @Transactional
    @Override
    public void generateWorkflowRecord() {
        // 生成项目风险管控历史数据
        Map<String,Object> queryPram = new HashMap<>();
        queryPram.put("startNum",0);
        queryPram.put("pageSize",10000);
        List<WorkFlow> workFlowList = workFlowDao.pageWorkflowList(queryPram);
        Map<String,Map<String,Object>> workflowConfigMap = workFlowConfigDao.getWorkflowConfigMap();
        List<WorkFlow> workFlowFilterList = new ArrayList<>();
        for (WorkFlow workFlow: workFlowList) {
            if (!workflowConfigMap.containsKey(workFlow.getConfigId())) {
                continue;
            }
            if ((int)workflowConfigMap.get(workFlow.getConfigId()).get("businessType") == 3) {
                continue;
            }
            workFlowFilterList.add(workFlow);
        }
        List<PatentRisk> patentRiskList = patentRiskDao.getPatentRiskList();
        List<PatentRiskHistory> patentRiskHistoryList = new ArrayList<>();
        for (PatentRisk patentRisk : patentRiskList) {
            for(WorkFlow workFlow:  workFlowFilterList) {
                if (!StringUtils.equals(patentRisk.getProjectId(),workFlow.getBusinessId()) ) {
                    continue;
                }
                PatentRiskHistory history = new PatentRiskHistory(patentRisk);
                history.setId(SnowFlake.nextIdStr());
                history.setProcessId(workFlow.getId());
                patentRiskHistoryList.add(history);
            }
        }
        List<PatentProposal> patentProposalList = patentProposalDao.getPatentProposalList();
        List<PatentProposalHistory> patentProposalHistoryList = new ArrayList<>();
        for (PatentProposal patentProposal : patentProposalList) {
            for(WorkFlow workFlow:  workFlowFilterList) {
                if (!StringUtils.equals(patentProposal.getProjectId(),workFlow.getBusinessId()) ) {
                    continue;
                }
                PatentProposalHistory history = new PatentProposalHistory(patentProposal);
                history.setId(SnowFlake.nextIdStr());
                history.setProcessId(workFlow.getId());
                patentProposalHistoryList.add(history);
            }
        }
        if (!patentRiskHistoryList.isEmpty()) {
            patentRiskHistoryDao.insertBatch(patentRiskHistoryList);
        }
        if (!patentProposalHistoryList.isEmpty()) {
            patentProposalHistoryDao.insertBatch(patentProposalHistoryList);
        }
    }

    /**
     * 创建待办任务
     *
     * @param currentTime 时间
     * @param content     内容
     * @param businessId  业务id
     * @param targetUser  目标用户
     * @return 待办任务
     */
    private UserMatter createMatter(String currentTime, String content, String businessId, String targetUser) {
        UserMatter userMatter = new UserMatter();
        userMatter.setId(SnowFlake.nextIdStr());
        userMatter.setCreateTime(currentTime);
        userMatter.setContent(content);

        userMatter.setStatus(0);
        userMatter.setSourceId(businessId);
        userMatter.setPendingUser(targetUser);
        return userMatter;
    }

    private String projectPatentDutyDeal(Project project) {
        PatentDepartment dep = patentDepartmentDao.selectById(project.getDepartment());
//        if (StringUtils.isEmpty(dep.getDutyUser())) {
//            return "";
//        }
        return dep.getDutyUser();
    }

    private String projectDepManagerDeal(Project project) {
        PatentDepartment dep = patentDepartmentDao.selectById(project.getDepartment());
        return dep.getManage();
    }

    private String projectSuperDepManagerDeal(Project project) {
        Map<String, PatentDepartmentSpecial> specialMap = patentDepartmentSpecialDao.getDepartmentBranchMap();
        return specialMap.containsKey(project.getDepartment()) ? specialMap.get(project.getDepartment()).getSpecialUser() : "";
    }

    /**
     * 创建流程节点记录
     *
     * @param nodeConfig  节点配置
     * @param workflowId  流程id
     * @param currentTime 当前时间
     * @param createUser  创建用户
     * @param dealUser    处理用户
     * @return 流程节点记录
     */
    private WorkFlowNodeRecord creatWorkFlowNodeRecord(WorkFlowNodeConfig nodeConfig, String workflowId, String currentTime, String createUser, String dealUser) {
        WorkFlowNodeRecord workFlowNodeRecord = new WorkFlowNodeRecord();
        workFlowNodeRecord.setId(SnowFlake.nextIdStr());
        workFlowNodeRecord.setNode(nodeConfig.getSortNum());
        workFlowNodeRecord.setWorkflowId(workflowId);
        workFlowNodeRecord.setCreateTime(currentTime);
        workFlowNodeRecord.setCreateUser(createUser);
        workFlowNodeRecord.setDealUser(dealUser);
        workFlowNodeRecord.setStatus(nodeConfig.getSortNum() == 1 ? 2 : 1);
        return workFlowNodeRecord;
    }

    /**
     * 退回逻辑
     *
     * @param workFlow    工作流信息
     * @param currentTime 当前时间
     * @param currentUser 当前用户
     */
    private void sendBack(WorkFlow workFlow, String currentTime, User currentUser) {
        workFlow.setStatus(3);
        workFlow.setCurrentNode(1);
        workFlow.setUpdateTime(currentTime);
        workFlow.setUpdateUser(currentUser.getId());
        workFlowDao.updateById(workFlow);

        WorkFlowNodeConfig nodeConfig = workFlowNodeConfigDao.getByWorkflowNode(workFlow.getConfigId(), workFlow.getCurrentNode() + 1);
        WorkFlowConfig workFlowConfig = workFlowConfigDao.selectById(workFlow.getConfigId());
        PatentRiskProcess process = new PatentRiskProcess();
        if (workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() ||
                workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue()) {
            ProjectPatentExpand patentExpand = projectPatentExpandDao.selectById(workFlow.getBusinessId());
            patentExpand.setChildStage(workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() ? 1 : 3);
            patentExpand.setUpdateUser(currentUser.getId());
            patentExpand.setUpdateTime(currentTime);
            projectPatentExpandDao.updateById(patentExpand);
            process = patentRiskProcessDao.getCurrentSort(workFlow.getBusinessId());
            process.setStatus(3);
            process.setEndTime(currentTime);
            patentRiskProcessDao.updateById(process);
        }

        if (workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue()) {
            List<PatentRisk> patentRiskList = patentRiskDao.getProcessPatentRiskList(workFlow.getBusinessId(), process.getSortNum());
            List<PatentRisk> updateList = new ArrayList<>(patentRiskList.size());
            for (PatentRisk risk : patentRiskList) {
                risk.setProcessNode(0);
                updateList.add(risk);
            }
            if (!updateList.isEmpty()) {
                patentRiskDao.updateBatchById(updateList);
            }
        }
        // 消息推送 "[ " + nodeConfig.getNodeName() + " ] 流程被"
        String content = "[ " + currentUser.getName() + " ] 拒绝了您的审批单，点击查看详情！";
        List<String> messageList = new ArrayList<>();
        messageList.add(workFlow.getCreateUser());
        MessageConfiguration messageConfiguration = new MessageConfiguration();
        messageConfiguration.setBusinessType(MessagePushBusinessEnum.PATENT_RISK_PROCESS.getValue());
        messageConfiguration.setContent(content);
        messageConfiguration.setContentType(MessageContentTypeEnum.TEXT_CARD.getValue());
        weChatMessageInterface.pushMessage(messageList, null, messageConfiguration, currentTime);
    }

    /**
     * 下一流程节点
     *
     * @param workFlow    工作流信息
     * @param currentTime 当前时间
     * @param currentUser 当前用户
     */
    private void nextFlow(WorkFlow workFlow, String currentTime, User currentUser) {
        WorkFlowNodeConfig nodeConfig = workFlowNodeConfigDao.getByWorkflowNode(workFlow.getConfigId(), workFlow.getCurrentNode() + 1);
        if (ObjectUtils.isEmpty(nodeConfig)) {
            return;
        }
        workFlow.setCurrentNode(nodeConfig.getSortNum());
        workFlow.setUpdateTime(currentTime);
        workFlow.setUpdateUser(currentUser.getId());
        String workflowId = workFlow.getId();
        List<String> messageList = new ArrayList<>();
        WorkFlowConfig workFlowConfig = workFlowConfigDao.selectById(workFlow.getConfigId());
        if (nodeConfig.getNodeType() == 2) {
            workFlow.setStatus(2);
            workFlowDao.updateById(workFlow);
            WorkFlowNodeRecord workFlowNodeRecord = new WorkFlowNodeRecord();
            workFlowNodeRecord.setId(SnowFlake.nextIdStr());
            workFlowNodeRecord.setWorkflowId(workflowId);
            workFlowNodeRecord.setStatus(2);
            workFlowNodeRecord.setNode(nodeConfig.getSortNum());
            workFlowNodeRecord.setDealUser(workFlow.getCreateUser());
            workFlowNodeRecord.setResult(1);
            workFlowNodeRecord.setCreateTime(currentTime);
            workFlowNodeRecord.setCreateUser(currentUser.getId());
            workFlowNodeRecord.setRemark("流程结束，自动关闭");
            workFlowNodeRecordDao.insert(workFlowNodeRecord);
            // 消息推送 "[ " + nodeConfig.getNodeName() + " ] "
            String content = "您的审批单已审批通过，点击查看详情！";
            messageList.add(workFlow.getCreateUser());
            MessageConfiguration messageConfiguration = new MessageConfiguration();
            messageConfiguration.setBusinessType(MessagePushBusinessEnum.PATENT_RISK_PROCESS.getValue());
            messageConfiguration.setContent(content);
            messageConfiguration.setContentType(MessageContentTypeEnum.TEXT_CARD.getValue());
            weChatMessageInterface.pushMessage(messageList, null, messageConfiguration, currentTime);
            ProjectPatentExpand patentExpand = null;
            if (workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() ||
                    workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue()) {
                patentExpand = projectPatentExpandDao.selectById(workFlow.getBusinessId());
                patentExpand.setChildStage(workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() ? 3 : 5);
                patentExpand.setUpdateUser(currentUser.getId());
                patentExpand.setUpdateTime(currentTime);
                projectPatentExpandDao.updateById(patentExpand);
            }
            if (workFlowConfig.getBusinessType() == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue()) {
                PatentRiskProcess process = patentRiskProcessDao.getCurrentSort(workFlow.getBusinessId());
                process.setStatus(2);
                process.setConclusion(PatentRiskTypeEnum.getNameByValue(patentExpand.getRiskStatus()));
                Map<String,Map<String,String>> userMap = userDao.getUserMap();
                List<WorkFlowNodeRecord> workFlowNodeRecordList = workFlowNodeRecordDao.getWorkflowRecord(workflowId);
                Set<String> assessorSet = new HashSet<>();
                for (WorkFlowNodeRecord record : workFlowNodeRecordList) {
                    assessorSet.add(userMap.get(record.getDealUser()).get("name"));
                }
                process.setAssessor(StringUtils.strip(assessorSet.toString().replaceAll(" ", "").replaceAll(",null", "").replaceAll(",,", ","), "[]"));
                process.setEndTime(currentTime);
                patentRiskProcessDao.updateById(process);
            }
            return;
        }
        Project project = projectDao.selectById(workFlow.getBusinessId());
        List<WorkFlowNodeRecord> recordAddList = new ArrayList<>();
        List<UserMatter> addMatterList = new ArrayList<>();

        Map<String, Map<String, String>> groupMap = workFlowGroupDao.getGroupMap();

//        String content = nodeConfig.getNodeType() == 1 ? "待办任务" : "流程待处理";
        int configType = workFlowConfig.getBusinessType();
        User createUser = userDao.selectById(workFlow.getCreateUser());
        String content = "用户 " + createUser.getName() + " 发起" +
                (configType == WorkflowTypeEnum.PATENT_INVESTIGATION.getValue() ? "项目风险排查" :
                        configType == WorkflowTypeEnum.PATENT_RISK_ANALYSIS.getValue() ? "新品专利风险分析" :
                                configType == WorkflowTypeEnum.PATENT_RISK.getValue() ? "风险专利评估" : "")
                + "需求，请登录审批";
        if (StringUtils.isEmpty(nodeConfig.getOperateUser())) {
            // 增加待处理用户组
            List<String> groupList = Arrays.asList(nodeConfig.getOperateGroup().split(","));
            for (String group : groupList) {
                String matchUser = matchSystemGroup(group, project);
                if (!StringUtils.equals(matchUser, "noMatch")) {
                    if (matchUser.contains(",")) {
                        List<String> userList = Arrays.asList(matchUser.split(","));
                        messageList.addAll(userList);
                        for (String u : userList) {
                            WorkFlowNodeRecord workFlowNodeRecord = creatWorkFlowNodeRecord(nodeConfig, workflowId, currentTime, currentUser.getId(), u);
                            recordAddList.add(workFlowNodeRecord);
                            UserMatter userMatter = createMatter(currentTime, content, workflowId, u);
                            userMatter.setSourceType(workFlowConfig.getBusinessType() + 6);
                            addMatterList.add(userMatter);
                        }
                        continue;
                    }
                    messageList.add(matchUser);
                    WorkFlowNodeRecord workFlowNodeRecord = creatWorkFlowNodeRecord(nodeConfig, workflowId, currentTime, currentUser.getId(), matchUser);
                    recordAddList.add(workFlowNodeRecord);
                    UserMatter userMatter = createMatter(currentTime, content, workflowId, matchUser);
                    userMatter.setSourceType(workFlowConfig.getBusinessType() + 6);
                    addMatterList.add(userMatter);
                    continue;
                }
                List<String> groupUserList = Arrays.asList(groupMap.get(group).get("groupUser").split(","));
                for (String groupUser : groupUserList) {
                    UserMatter userMatter = createMatter(currentTime, content, workflowId, groupUser);
                    userMatter.setSourceType(workFlowConfig.getBusinessType() + 6);
                    addMatterList.add(userMatter);
                    WorkFlowNodeRecord workFlowNodeRecord = creatWorkFlowNodeRecord(nodeConfig, workflowId, currentTime, currentUser.getId(), groupUser);
                    recordAddList.add(workFlowNodeRecord);
                }
                messageList.addAll(groupUserList);
            }
        } else {
            List<String> targetUserList = Arrays.asList(nodeConfig.getOperateUser().split(","));
            for (String targetUser : targetUserList) {
                UserMatter userMatter = createMatter(currentTime, content, workflowId, targetUser);
                userMatter.setSourceType(workFlowConfig.getBusinessType() + 6);
                addMatterList.add(userMatter);
                WorkFlowNodeRecord workFlowNodeRecord = creatWorkFlowNodeRecord(nodeConfig, workflowId, currentTime, currentUser.getId(), targetUser);
                recordAddList.add(workFlowNodeRecord);
            }
            messageList.addAll(targetUserList);
        }
        if (!addMatterList.isEmpty()) {
            userMatterDao.insertBatch(addMatterList);
        }
        if (nodeConfig.getNoticeType() == 1) {
            MessageConfiguration messageConfiguration = new MessageConfiguration();
            messageConfiguration.setBusinessType(MessagePushBusinessEnum.PATENT_RISK_PROCESS.getValue());
            messageConfiguration.setContent(content);
            messageConfiguration.setContentType(MessageContentTypeEnum.TEXT_CARD.getValue());
            weChatMessageInterface.pushMessage(messageList, null, messageConfiguration, currentTime);
        }
        if (!recordAddList.isEmpty()) {
            workFlowNodeRecordDao.insertBatch(recordAddList);
        }
        workFlowDao.updateById(workFlow);
    }

    /**
     * 匹配用户是否在系统用户组
     *
     * @param group   用户组
     * @param project 项目信息
     * @return 用户是否在系统用户组
     */
    private String matchSystemGroup(String group, Project project) {
        String systemUser = "";
        boolean match = false;
        if (StringUtils.equals(group, "1")) {
            systemUser = projectDepManagerDeal(project);
            match = true;
        } else if (StringUtils.equals(group, "2")) {
            systemUser = project.getProjectManager();
            match = true;
        } else if (StringUtils.equals(group, "3")) {
            systemUser = projectSuperDepManagerDeal(project);
            match = true;
        } else if (StringUtils.equals(group, "4")) {
            systemUser = projectPatentDutyDeal(project);
            match = true;
        }

        return match ? systemUser : "noMatch";
    }

    /**
     * 构建项目信息
     *
     * @param project 项目
     * @param userMap 用户map
     * @return 项目信息
     */
    private Map<String, Object> buildProject(Project project, Map<String, Map<String, String>> userMap) {
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        Map<String, Object> map = ObjectUtils.object2Map(project);
        map.put("statusName", DifficultyStatusEnum.getNameByValue(project.getStatus()));
        map.put("projectTypeName",project.getProjectType() == 1 ? "预研项目" : project.getProjectType() == 2 ? "新品开发" : project.getProjectType() == 3 ? "其他" : "未知类型");
        map.put("dealStatusName", ProjectDealEnum.getNameByValue(project.getDealStatus()));
        if (userMap.containsKey(project.getProjectManager())) {
            Map<String, String> projectManagerMap = userMap.get(project.getProjectManager());
            map.put("projectManagerName", projectManagerMap.get("name"));
            map.put("projectManagerContact", projectManagerMap.get("email"));
        } else {
            map.put("projectManagerName", "");
            map.put("projectManagerContact", "");
        }
        map.put("projectLevelName", ProjectLevelEnum.getNameByValue(project.getProjectLevel()));
        map.put("createUserName", userMap.containsKey(project.getCreateUser()) ? userMap.get(project.getCreateUser()).get("name") : project.getCreateUser());
        map.put("projectSourceName", ProjectSourceEnum.getNameByValue(project.getProjectSource()));
        map.put("departmentName", departmentMap.containsKey(project.getDepartment()) ? departmentMap.get(project.getDepartment()).get("name") : "");
        return map;
    }

    /**
     * 备份数据
     *
     * @param businessId 业务id
     * @param workflowId 流程id
     */
    private void backupData(String businessId,String workflowId){
        Map<String,Object> queryParam = new HashMap<>();
        queryParam.put("projectId",businessId);
        queryParam.put("startNum",0);
        queryParam.put("pageSize",10000);
        // 风险点数据备份
        List<PatentRisk> patentRiskList = patentRiskDao.pagePatentRiskList(queryParam);
        List<PatentRiskHistory> patentRiskHistoryList = new ArrayList<>(patentRiskList.size());
        for (PatentRisk risk: patentRiskList) {
            PatentRiskHistory patentRiskHistory = new PatentRiskHistory(risk);
            patentRiskHistory.setProcessId(workflowId);
            patentRiskHistory.setId(SnowFlake.nextIdStr());
            patentRiskHistoryList.add(patentRiskHistory);
        }
        if (!ObjectUtils.isEmpty(patentRiskHistoryList)) {
            patentRiskHistoryDao.insertBatch(patentRiskHistoryList);
        }
        // 风险专利数据备份
        List<PatentProposal> patentProposalList = patentProposalDao.pagePatentProposalList(queryParam);
        List<PatentProposalHistory> patentProposalHistoryList = new ArrayList<>(patentProposalList.size());
        for (PatentProposal proposal: patentProposalList) {
            PatentProposalHistory patentProposalHistory = new PatentProposalHistory(proposal);
            patentProposalHistory.setProcessId(workflowId);
            patentProposalHistory.setId(SnowFlake.nextIdStr());
            patentProposalHistoryList.add(patentProposalHistory);
        }
        if (!ObjectUtils.isEmpty(patentProposalHistoryList)) {
            patentProposalHistoryDao.insertBatch(patentProposalHistoryList);
        }
    }
}
